package com.cema.manage.project.manage.userDailyActivity.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.cema.manage.common.utils.AddressUtils;
import com.cema.manage.common.utils.IpUtils;
import com.cema.manage.project.android.model.UserDailyActivityVo;
import com.cema.manage.project.enums.RedisEnum;
import com.cema.manage.project.enums.RiskEnum;
import com.cema.manage.project.manage.antiCheatDetail.domain.AntiCheatDetail;
import com.cema.manage.project.manage.antiCheatDetail.service.IAntiCheatDetailService;
import com.cema.manage.project.manage.userDailyActivity.domain.UserDailyActivity;
import com.cema.manage.project.manage.userDailyActivity.domain.UserDailyActivityDto;
import com.cema.manage.project.manage.userDailyActivity.mapper.UserDailyActivityMapper;
import com.cema.manage.project.manage.users.domain.Users;
import com.cema.manage.project.manage.users.service.IUsersService;
import com.cema.manage.project.util.DateUtils;
import com.cema.manage.redis.RedisService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 用户日活 服务层实现
 *
 * @author reasahi
 * @date 2024-08-04
 */
@Service
public class UserDailyActivityServiceImpl extends ServiceImpl<UserDailyActivityMapper, UserDailyActivity> implements IUserDailyActivityService {
    @Resource
    private IUsersService usersService;

    @Resource
    private RedisService redisService;

    @Resource
    private IAntiCheatDetailService antiCheatDetailService;

    @Override
    public void saveUserDaily(Users users, String ip, UserDailyActivityVo userDailyActivityVo) throws UnknownHostException {
        Users upLoginUsers = new Users();
        upLoginUsers.setId(users.getId());
        upLoginUsers.setLoginIp(ip);
        upLoginUsers.setLoginTime(new Date());
        UserDailyActivity userDailyActivity = getUserDailyActivity(users, userDailyActivityVo);
        String key = (String) redisService.get(RedisEnum.LOCATION_AWKJ_PUBLIC_KEY.getKey());
        UserDailyActivityDto userDailyActivityDto = AddressUtils.getRealAddressByIp(key, ip);
        EntityWrapper<UserDailyActivity> entityWrapperUserDailyActivity = new EntityWrapper<>();
        entityWrapperUserDailyActivity.eq("us_id", users.getId());
        DateUtils.getCurrentDayTime(entityWrapperUserDailyActivity, "create_time");
        List<UserDailyActivity> userDailyActivityList = selectList(entityWrapperUserDailyActivity);
        long sameNetwork = IpUtils.getInSameNetwork(ip);
        if (ObjectUtil.isNull(userDailyActivityList) || userDailyActivityList.size() == 0) {
            int loginDayNumber = users.getLoginDayNumber() + 1;
            upLoginUsers.setLoginDayNumber(loginDayNumber);
            int loginInDayNumber = users.getLoginInDayNumber() + 1;
            upLoginUsers.setLoginInDayNumber(loginInDayNumber);
            userDailyActivity.setUsId(users.getId());
            userDailyActivity.setUdaIp(ip);
            userDailyActivity.setUdaIpSameNetwork(String.valueOf(sameNetwork));
            userDailyActivity.setUdaLng(userDailyActivityDto.getLng());
            userDailyActivity.setUdaLat(userDailyActivityDto.getLat());
            userDailyActivity.setUdaAddress(userDailyActivityDto.getAddress());
            userDailyActivity.setUsNickname(users.getNickname());
            insert(userDailyActivity);
        } else {
            EntityWrapper<UserDailyActivity> entityWrapper = new EntityWrapper<>();
            userDailyActivity.setUdaIp(ip);
            userDailyActivity.setUdaIpSameNetwork(String.valueOf(sameNetwork));
            userDailyActivity.setUdaLng(userDailyActivityDto.getLng());
            userDailyActivity.setUdaLat(userDailyActivityDto.getLat());
            userDailyActivity.setUdaAddress(userDailyActivityDto.getAddress());
            userDailyActivity.setUsNickname(users.getNickname());
            userDailyActivity.setCreateTime(new Date());
            entityWrapper.eq("us_id", users.getId());
            DateUtils.getCurrentDayTime(entityWrapper, "create_time");
            update(userDailyActivity, entityWrapper);
        }
        usersService.updateById(upLoginUsers);
    }

    @Override
    public void checkDeviceInfo(Users users, UserDailyActivityVo userDailyActivityVo) {
        Integer value = userDailyActivityVo.getUdaSeparation();
        if (ObjectUtil.isNull(value)) {
            return;
        }
        UserDailyActivity userDailyActivity = getUserDailyActivity(users, userDailyActivityVo);
        EntityWrapper<UserDailyActivity> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("us_id", users.getId());
        DateUtils.getCurrentDayTime(entityWrapper, "create_time");
        update(userDailyActivity, entityWrapper);
    }

    private UserDailyActivity getUserDailyActivity(Users users, UserDailyActivityVo userDailyActivityVo) {
        UserDailyActivity userDailyActivity = BeanUtil.toBean(userDailyActivityVo, UserDailyActivity.class);
        //双开 （后台封号）
        AntiCheatDetail antiCheatDetail = new AntiCheatDetail();
        antiCheatDetail.setUsId(users.getId());
        String riskDoubleOpenBackstage = (String) redisService.get(RedisEnum.RISK_DOUBLE_OPEN_BACKSTAGE.getKey()+userDailyActivityVo.getUvChannel());
        if (RiskEnum.RISK_YES.getValue().equals(riskDoubleOpenBackstage)) {
            Integer value = userDailyActivity.getUdaSeparation();
            if (ObjectUtil.isNotNull(value) && value == 1) {
                //封号处理
                antiCheatDetail.setAcdDesc("双开");
                saveStatus(antiCheatDetail, users);
                return userDailyActivity;
            }
        }
        //模拟器
        String riskSimulatoBackstage = (String) redisService.get(RedisEnum.RISK_SIMULATOR_BACKSTAGE.getKey()+userDailyActivityVo.getUvChannel());
        if (RiskEnum.RISK_YES.getValue().equals(riskSimulatoBackstage)) {
            Integer value = userDailyActivity.getUdaSimulator();
            if (ObjectUtil.isNotNull(value) && value == 1) {
                //封号处理
                antiCheatDetail.setAcdDesc("模拟器");
                saveStatus(antiCheatDetail, users);
                return userDailyActivity;
            }
        }
        //开启调试模式
        String riskDeveloperModeBackstage = (String) redisService.get(RedisEnum.RISK_DEVELOPER_MODE_BACKSTAGE.getKey()+userDailyActivityVo.getUvChannel());
        if (RiskEnum.RISK_YES.getValue().equals(riskDeveloperModeBackstage)) {
            Integer value = userDailyActivity.getUdaDebugMode();
            if (ObjectUtil.isNotNull(value) && value == 1) {
                //封号处理
                antiCheatDetail.setAcdDesc("开启调试模式");
                saveStatus(antiCheatDetail, users);
                return userDailyActivity;
            }
        }
        //是否USB调试模式
        String riskDebugModeBackstage = (String) redisService.get(RedisEnum.RISK_DEBUG_MODE_BACKSTAGE.getKey()+userDailyActivityVo.getUvChannel());
        if (RiskEnum.RISK_YES.getValue().equals(riskDebugModeBackstage)) {
            Integer value = userDailyActivity.getUdaUsbMode();
            if (ObjectUtil.isNotNull(value) && value == 1) {
                //封号处理
                antiCheatDetail.setAcdDesc("USB调试模式");
                saveStatus(antiCheatDetail, users);
                return userDailyActivity;
            }
        }
        //是否ROOT模式
        String riskRootBackstage = (String) redisService.get(RedisEnum.RISK_ROOT_BACKSTAGE.getKey()+userDailyActivityVo.getUvChannel());
        if (RiskEnum.RISK_YES.getValue().equals(riskRootBackstage)) {
            Integer value = userDailyActivity.getUdaRoot();
            if (ObjectUtil.isNotNull(value) && value == 1) {
                //封号处理
                antiCheatDetail.setAcdDesc("ROOT模式");
                saveStatus(antiCheatDetail, users);
                return userDailyActivity;
            }
        }
        //是否开启无障碍模式
        String riskAccessibilityBackstage = (String) redisService.get(RedisEnum.RISK_ACCESSIBILITY_BACKSTAGE.getKey()+userDailyActivityVo.getUvChannel());
        if (RiskEnum.RISK_YES.getValue().equals(riskAccessibilityBackstage)) {
            Integer value = userDailyActivity.getUdaAccessibility();
            if (ObjectUtil.isNotNull(value) && value == 1) {
                //封号处理
                antiCheatDetail.setAcdDesc("开启无障碍模式");
                saveStatus(antiCheatDetail, users);
                return userDailyActivity;
            }
        }

        //是否开启VIP代理
        String riskIdProxyBackstage = (String) redisService.get(RedisEnum.RISK_ID_PROXY_BACKSTAGE.getKey()+userDailyActivityVo.getUvChannel());
        if (RiskEnum.RISK_YES.getValue().equals(riskIdProxyBackstage)) {
            Integer value = userDailyActivity.getUdaVpnProxy();
            if (ObjectUtil.isNotNull(value) && value == 1) {
                //封号处理
                antiCheatDetail.setAcdDesc("开启VPN代理");
                saveStatus(antiCheatDetail, users);
                return userDailyActivity;
            }
        }
        //黑名单验证 TODO
        String riskAppBlackList = (String) redisService.get(RedisEnum.RISK_APP_BLACK_LIST.getKey()+userDailyActivityVo.getUvChannel());
        if (StrUtil.isNotEmpty(riskAppBlackList)) {
            String udaAllAppDetail = userDailyActivity.getUdaAllAppDetail();
            JSONArray jsonArray = JSONUtil.parseArray(udaAllAppDetail);
            List<String> strAppNames = new ArrayList<>();
            List<String> strUdaPackage = new ArrayList<>();
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                strAppNames.add(jsonObject.getStr("udaAppName"));
                strUdaPackage.add(jsonObject.getStr("udaPackage"));
            }
            List<String> appBackList = new ArrayList<>(Arrays.asList(riskAppBlackList.split(StrUtil.COMMA)));
            // 找出相同的元素
            List<String> intersection = new ArrayList<>(appBackList);
            intersection.retainAll(strAppNames);
            if (intersection.size() > 0) {
                antiCheatDetail.setAcdDesc("当前设备不可信");
                saveStatus(antiCheatDetail, users);
                return userDailyActivity;
            }
            List<String> intersectionPackage = new ArrayList<>(appBackList);
            intersectionPackage.retainAll(strUdaPackage);
            if (intersectionPackage.size() > 0) {
                antiCheatDetail.setAcdDesc("当前设备不可信");
                saveStatus(antiCheatDetail, users);
            }
        }
        return userDailyActivity;
    }

    @Override
    public List<UserDailyActivityDto> getUserDailyActivity(String currentTime) {
        EntityWrapper<UserDailyActivity> entityWrapper = new EntityWrapper<>();
        if (StrUtil.isNotEmpty(currentTime)) {
            DateUtils.getCurrentDayTime(entityWrapper, currentTime, "create_time");
        } else {
            DateUtils.getCurrentDayTime(entityWrapper, "create_time");
        }
        List<UserDailyActivity> userDailyActivityList = selectList(entityWrapper);
        if (ObjectUtil.isNull(userDailyActivityList)) {
            return new ArrayList<>();
        }
        List<UserDailyActivityDto> userDailyActivityDtos = new ArrayList<>(userDailyActivityList.size());
        for (UserDailyActivity userDailyActivity : userDailyActivityList) {
            UserDailyActivityDto userDailyActivityDto = new UserDailyActivityDto();
            userDailyActivityDto.setLat(userDailyActivity.getUdaLat());
            userDailyActivityDto.setLng(userDailyActivity.getUdaLng());
            userDailyActivityDto.setUserId(userDailyActivity.getUsId());
            userDailyActivityDtos.add(userDailyActivityDto);
        }
        return userDailyActivityDtos;
    }


    /**
     * 保存封号记录
     */
    @Override
    public void saveStatus(AntiCheatDetail antiCheatDetail, Users users) {
        //每个用户只能添加一次
        EntityWrapper<AntiCheatDetail> entityWrapper = new EntityWrapper<>();
        AntiCheatDetail antiCheatDetailEntity = new AntiCheatDetail();
        antiCheatDetailEntity.setUsId(users.getId());
        entityWrapper.setEntity(antiCheatDetailEntity);
        int count = antiCheatDetailService.selectCount(entityWrapper);
        if (count > 0) {
            return;
        }
        if (antiCheatDetailService.insert(antiCheatDetail)) {
            users.setStatus(2);
            usersService.setStatus(users);
        }
    }

    @Override
    public void updateUserDailySeparation(Integer usId) {
        EntityWrapper<UserDailyActivity> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("us_id", usId);
        DateUtils.getCurrentDayTime(entityWrapper, "create_time");
        UserDailyActivity userDailyActivity = new UserDailyActivity();
        userDailyActivity.setUdaSeparation(Integer.valueOf(RiskEnum.RISK_YES.getValue()));
        update(userDailyActivity, entityWrapper);
    }
}
